/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using EXtremecode.Utils;
using EXtremecode.Common;
using System.Data;
using System.Data.SqlClient;
using EXtremecode.DataAccessLayer;
namespace EXtremecode.DataAccessLayer
{
	
	
	
	
	public class DAAdapter:IPooledObject 
	{
        private ObjectPool m_pool;
        private IDbDataAdapter m_adapter;
		private IDbDataAdapter m_adapterTransaction;
		private DataAccessor m_da;
		private DACommand m_cmdSelect,m_cmdUpdate,m_cmdInsert,m_cmdDelete;
		private FieldInfoCollection m_fields;
		public DAAdapter(IDbDataAdapter adapter,DataAccessor da,IDbDataAdapter adapterTransaction,FieldInfoCollection fields)
		{
			try
			{
				m_adapter=adapter;
				m_adapterTransaction=adapterTransaction; 
				m_da=da;
				m_fields=fields;
				if(m_adapter!=null)
				{
					m_cmdSelect=new DACommand(adapter.SelectCommand,da,adapterTransaction.SelectCommand,m_fields,CommandAction.Select); 
					m_cmdDelete=new DACommand(adapter.DeleteCommand,da,adapterTransaction.DeleteCommand,m_fields,CommandAction.Delete); 
					m_cmdInsert=new DACommand(adapter.InsertCommand,da,adapterTransaction.InsertCommand,m_fields,CommandAction.Insert); 
					m_cmdUpdate=new DACommand(adapter.UpdateCommand,da,adapterTransaction.UpdateCommand,m_fields,CommandAction.Update); 
				}
				else
				{
					m_cmdSelect=new DACommand(null,da,null,CommandAction.Select); 
					m_cmdDelete=new DACommand(null,da,null,CommandAction.Delete); 
					m_cmdInsert=new DACommand(null,da,null,CommandAction.Insert); 
					m_cmdUpdate=new DACommand(null,da,null,CommandAction.Update); 

				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}

		}
		
		public void FillFromCache(DataTable dt)
		{
			DADataReader daRdr=m_cmdSelect.GetDataReaderFromCache();
			DataRowReader rdr= daRdr.ClassicDataReader as DataRowReader;
			try
			{
				dt.BeginLoadData();
				while(rdr.Read())
				{
					dt.LoadDataRow(rdr.CurrentDataRow.ItemArray,true);
				}
			}
			finally
			{
				dt.EndLoadData();
			}
			
		}
		public void Fill(DataTable dt)
		{
			try
			{
				
				if(m_adapter==null)throw new Exception("Method is not available in the [offline] mode");
				string strOriginalTableName=dt.TableName;
				dt.TableName="Table";
				DataSet dsOwner=dt.DataSet;
				DataSet ds;
			
				if(dsOwner == null) 
				{
					ds = new DataSet();
					ds.Tables.Add(dt);
				}
				else
				{
					ds=dsOwner;
				}
				try
				{
					SelectCommand.ArrangeQuery();
					m_adapter.Fill(ds);
					SelectCommand.RearrangeAfterExecution();
				}
				catch(Exception ex)
				{
					throw ex;  
				}
				finally
				{
					SelectCommand.AddDeletedParams();
					if(dsOwner==null) ds.Tables.Clear();
					dt.TableName=strOriginalTableName;
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(string.Format("Table Name = '{0}'",dt.TableName),ex);
			}
			finally
			{
				Logging.Logger.Write();
			}


		}
		public void FillForTransaction(DataTable dt)
		{
			try
			{
				
				if(m_adapterTransaction==null)throw new Exception("Method is not available in the [offline] mode");
				string strOriginalTableName=dt.TableName;
				dt.TableName="Table";
				DataSet dsOwner=dt.DataSet;
				DataSet ds;
			
				if(dsOwner == null) 
				{
					ds = new DataSet();
					ds.Tables.Add(dt);
				}
				else
				{
					ds=dsOwner;
				}
				try
				{
					SetTransaction();
					SelectCommand.ArrangeQuery(true);
					m_adapterTransaction.Fill(ds);
					SelectCommand.RearrangeAfterExecution(true);
				}
				catch(Exception ex)
				{
					throw ex;  
				}
				finally
				{
					SelectCommand.AddDeletedParams(true);
					if(dsOwner==null) ds.Tables.Clear();
					dt.TableName=strOriginalTableName;
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(string.Format("Table Name = '{0}'",dt.TableName),ex);
			}
			finally
			{
				Logging.Logger.Write();
			}


		}

		public void FillSchema(DataTable dt)
		{
			
			try
			{
				if(m_adapter==null)throw new Exception("Method is not available in the [offline] mode");
				if(!ValidateQuery())return;
				string strOriginalTableName=dt.TableName;
				dt.TableName="Table";
				DataSet dsOwner=dt.DataSet;
				DataSet ds;
				if(dsOwner == null) 
				{
					ds = new DataSet();
					ds.Tables.Add(dt);
				}
				else
				{
					ds=dsOwner;
				}
				try
				{
					SelectCommand.ArrangeQuery();
					m_adapter.FillSchema(ds,SchemaType.Source);
					SelectCommand.RearrangeAfterExecution();
				}
				finally
				{
					if(dsOwner==null) ds.Tables.Clear();
					dt.TableName=strOriginalTableName;
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}

		}
		private void Set_IgnoreConcurr_Property(DataTable dt,bool bIgnoreConcurrEx)
		{
			if(!dt.ExtendedProperties.Contains(Constants.KEY_IGNORE_CONCURRENCY))
				dt.ExtendedProperties.Add(Constants.KEY_IGNORE_CONCURRENCY,bIgnoreConcurrEx);
			else
				dt.ExtendedProperties[Constants.KEY_IGNORE_CONCURRENCY]=bIgnoreConcurrEx;
		}
		public void Update(DataTable dt,bool bIgnoreConcurrEx)
		{
			try
			{
				Set_IgnoreConcurr_Property(dt,bIgnoreConcurrEx);
				if(m_adapter==null)throw new Exception("Method is not available in the [offline] mode");
				string strOriginalTableName=dt.TableName;
				dt.TableName="Table";

				DataSet dsOwner=dt.DataSet;
				DataSet ds;
				if(dsOwner == null) 
				{
					ds = new DataSet();
					ds.Tables.Add(dt);
				}
				else
				{
					ds=dsOwner;
				}
				try
				{
				
					m_adapter.Update(ds);
				}
			
				finally
				{
					if(dsOwner==null) ds.Tables.Clear();
					dt.TableName=strOriginalTableName;
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}

			
		}
		public void Update(DataTable dt)
		{
			Update(dt,false);			
		}

		private void SetTransaction()
		{
			m_cmdSelect.Transaction=m_cmdUpdate.Transaction=m_cmdInsert.Transaction=m_cmdDelete.Transaction=m_da.Transaction;	
		}
		public void UpdateForTransaction(DataTable dt,bool bIgnoreConcurrEx)
		{
			try
			{
				Set_IgnoreConcurr_Property(dt,bIgnoreConcurrEx);
				if(m_adapterTransaction==null)throw new Exception("Method is not available in the [offline] mode");
				if(!ValidateQuery())return;
				string strOriginalTableName=dt.TableName;
				dt.TableName="Table";

				DataSet dsOwner=dt.DataSet;
				DataSet ds;
				if(dsOwner == null) 
				{
					ds = new DataSet();
					ds.Tables.Add(dt);
				}
				else
				{
					ds=dsOwner;
				}
				try
				{
					SetTransaction();
					m_adapterTransaction.Update(ds);
				}
				catch(Exception ex)
				{
					DataAccessorCollection.Instance.Rollback();
					throw ex;
				}
				finally
				{
					if(dsOwner==null) ds.Tables.Clear();
					dt.TableName=strOriginalTableName;
				}
			}
			catch(Exception ex)
			{
				throw Logging.Logger.Write(ex);
			}
			finally
			{
				Logging.Logger.Write();
			}

			
		}

		public void UpdateForTransaction(DataTable dt)
		{
			UpdateForTransaction(dt,false);			
		}
		private bool ValidateQuery()
		{
			return (m_adapter.UpdateCommand.Parameters.Count>0);//Means its a view n updata command is not valid;
		}

		public DACommand SelectCommand
		{
			get
			{
				return m_cmdSelect; 
			}
		}

		public DACommand UpdateCommand
		{
			get
			{
				return m_cmdUpdate; 

			}
		}

		public DACommand InsertCommand
		{
			get
			{
				return m_cmdInsert; 

			}
		}

		public DACommand DeleteCommand
		{
			get
			{
				return m_cmdDelete; 

			}
		}



        #region IPooledObject Members

        public ObjectPool Pool
        {
            get
            {
                return m_pool; ;
            }
            set
            {
                m_pool = value;
            }
        }

        #endregion
    }
}
